package cn.imvc.app.models;

import java.util.Date;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import com.puff.cache.redis.Redis;

import cn.imvc.app.domains.Constants;
import cn.imvc.app.domains.PageDomain;
import cn.imvc.app.entities.Article;
import cn.imvc.app.entities.ArticleClass;
import cn.imvc.app.repositories.ArticleRepository;
import cn.imvc.core.ICache;
import cn.imvc.data.domain.ViewRequest;
import cn.imvc.util.ToolUtils;

@Service
public class ArticleModelImpl implements ArticleModel {

	@Autowired
	private ArticleRepository articleRepository;

	@Autowired
	MemberModel memberModel;

	@Autowired
	CommonModel commonModel;

	@Autowired
	ArticleClassModel articleClassModel;

	@Autowired
	ICache cache;

	public Article get(int id) {
		Integer articleMaxId = commonModel.findMaxId("article");
		if (id > articleMaxId) {
			return null;
		}
		Article article = null;
		String key = "ARTICLE_" + id;
		int minute = ToolUtils.getMinute(new Date());
		while (true) {
			article = cache.get("DATA", key);
			if (article == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					article = articleRepository.findOne(id);
					cache.put("DATA", key, article, 3600);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				break;
			}
		}
		return article;
	}

	public Page<Article> find(ViewRequest viewRequest) {
		return (Page<Article>) articleRepository.findAll();
	}

	public Article save(Article article) {
		return  articleRepository.saveAndFlush(article);
	}

	public Article update(Article newArticle) {
		Article loadArticle = get(newArticle.getId());
		BeanUtils.copyProperties(newArticle, loadArticle, new String[] { "id" });
		return articleRepository.saveAndFlush(loadArticle);
	}

	public void delete(int id) {
		articleRepository.delete(id);
	}

	public void deleteBatch(int[] ids) {
		for (int id : ids) {
			delete(id);
		}
	}

	@Override
	public Page<Article> findArticleListByArticleClass(Integer articleClassId, Integer page, Integer pageSize) {
		Integer articleClassMaxId = commonModel.findMaxId("articleClass");
		if (articleClassMaxId == null || articleClassId == null || (articleClassMaxId != null && articleClassId > articleClassMaxId)) {
			return null;
		}
		PageDomain<Article> domain = null;
		Page<Article> list = null;
		if(page == null){
			page = 0;
		}
		String key = "ARTICLECLASS_" + articleClassId + "_" + page;
		int minute = ToolUtils.getMinute(new Date());
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					PageRequest pageRequest;
					if(pageSize == null || (pageSize != null && pageSize == 0)){
						pageRequest = new PageRequest(page, Constants.ARTICLE_PAGE_SIZE, null);
					} else {
						pageRequest = new PageRequest(page, pageSize, null);
					}
					ArticleClass articleClass = articleClassModel.get(articleClassId);
					if(articleClassId == 0 || articleClass == null){
						list = articleRepository.findByIsShowOrderByTimeDesc((byte) 1, pageRequest);
					} else {
						list = articleRepository.findByArticleClassAndIsShowOrderByTimeDesc(articleClass, (byte) 1, pageRequest);
					}
					domain = new PageDomain<Article>();
					domain.setPage(list);
					cache.put("DATA", key, domain, 3600);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				list = domain.getPage();
				break;
			}
		}
		return list;
	}
	public List<Object[]> findMaxId(){
		return articleRepository.findAllSql("select max(id) from article"); 
	}
	
	public Article findByTitleAndArticleClass(String title, Integer articleClassId) {
		ArticleClass articleClass = articleClassModel.get(articleClassId);
		List<Article> list = articleRepository.findByTitleAndArticleClass(title, articleClass);
		if (list != null && list.size() > 0) {
			return list.get(0);
		} else {
			return null;
		}
	}
}
